#include "cmdsoul.h"
#include "commmsg.h"
#include "../mainctrl.h"
#include "../cmd/dataprepare.h"
#include "../soul/CSoulMgr.h"

CT_REGISTER_ASYNCCMD(ID_MAIN_SOUL , CCmdSoul);

int CCmdSoul::Do(void* pData)
{
    CT_ASSERT(pData);
    int iRet = 0;

    //解析消息
    CCmdPBDoParam* pstParam = (CCmdPBDoParam*) pData;
    pstMainCtrl = (CMainCtrl*) pstParam->m_pMain;

    if (pstParam->m_pstMsgHead->msgid() != ID_MAIN_SOUL ||
        pstParam->m_pstMsgHead->msgtype() != CSMsgDef::EMT_REQUEST)
    {
        CT_ERROR(("Cmd Stat Err Cmd=%d CmdID=%d Type=%d",
            ID_MAIN_SOUL,
            pstParam->m_pstMsgHead->msgid(),
            pstParam->m_pstMsgHead->msgtype()));
        return Done(RET_SYS_ERROR);
    }

    stMsgHead = *(pstParam->m_pstMsgHead);
    stEnpHead = *(pstParam->m_pstEnpHead);
    iRet = pstMainCtrl->DecodePBMsg(stReq, pstParam);
    if (iRet)
    {
        return AnsClients(iRet);
    }
    //消息解析结束

    uiGID = (unsigned int)stReq.gid();

    //检查登录
    iRet = pstMainCtrl->CheckLogin(uiGID, stEnpHead);
    if (iRet != RET_OK)
    {
        return AnsClients(iRet);
    }

    LogicDo(RET_OK);
    return iRet;
}

int CCmdSoul::LogicDo(int iRet)
{
    if (iRet != 0)
    {
        return AnsClients(iRet);
    }

    PREPARE_PLAYER_BASE_INFO(this, uiGID);
    ASSERT_PLAYER_PREPARED(uiGID);

    PREPARE_PLAYER_DETAIL_INFO(this, uiGID);
    ASSERT_PLAYER_DETAIL_PREPARED(uiGID);

    PREPARE_PLAYER_DETAIL_EX1_INFO(this, uiGID);
    ASSERT_PLAYER_DETAIL_EX1_INFO(uiGID);

    PREPARE_PLAYER_ONLINE_DATA(this, uiGID);

    int iIndex;
    iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerBaseInfo& stPlayerBaseInfo = pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];

    if (stPlayerBaseInfo._ucIsInited != 1)
    {
        return AnsClients(ERROR_NOT_INITED);
    }

    iIndex = pstMainCtrl->m_stPlayerDetailInfoHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerDetailInfo& stPlayerDetailInfo = pstMainCtrl->m_stPlayerDetailInfoHash[iIndex];
    stPlayerDetailInfo._stSoulData._uiGID = uiGID;

    iIndex = pstMainCtrl->m_stPlayerDetailEx1InfoHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        CT_ERROR(("get user detail ex1 info error, uid = %u", uiGID));
        return AnsClients(RET_SYSTEM_FAIL);
    }
    CPlayerDetailInfoEx1& stPlayerDetailEx1Info = pstMainCtrl->m_stPlayerDetailEx1InfoHash[iIndex];

    iIndex = pstMainCtrl->m_stPlayerOnlineDataHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        CT_ERROR(("user %u not in m_stPlayerOnlineDataHash", uiGID));
        pstMainCtrl->SetOffline(stPlayerBaseInfo._uiGID, stEnpHead);
        return AnsClients(RET_SYSTEM_FAIL);

    }
    CPlayerOnlineData& stPlayerOnlineData = pstMainCtrl->m_stPlayerOnlineDataHash[iIndex];

    //检查系统是否开启
    if (!pstMainCtrl->m_stCommConfigLoader.IsOpen(SYS_OPEN_COND_ID_5, stPlayerBaseInfo, stPlayerOnlineData))
    {
        return AnsClients(ERROR_SYS_NOT_OPEN);
    }

    unsigned char ucOptType = stReq.opt();
    stAns.set_opt(ucOptType);
    bool bNeedSaveData = false;

    switch(ucOptType)
    {
    case 1: //查询魂器信息
        {
            MsgSoulInfo* pstMsgSouInfo = stAns.mutable_info();
            stAns.set_now_hunli(stPlayerBaseInfo._iHunli);
            pstMsgSouInfo->set_now_skill_id(stPlayerOnlineData._stUserRole.GetMagicSkillID());
            iRet = pstMainCtrl->m_stSoulMgr.GetSoulInfo(stPlayerDetailInfo._stSoulData, *pstMsgSouInfo);
        }
        break;
    case 2: //升级
        {
            bool bIsStatUp = false;
            unsigned char ucBallID = (unsigned char)stReq.opt_ball_id();

            MsgBallInfo* pstMsgBallInfo = stAns.mutable_opt_ball_info();
            iRet = pstMainCtrl->m_stSoulMgr.LevelUp(stPlayerDetailInfo._stSoulData, stPlayerBaseInfo._iHunli, 
                                    (unsigned short)stPlayerBaseInfo._shLevel, ucBallID, bIsStatUp, *pstMsgBallInfo);
            if (iRet != 0)
            {
                return AnsClients(iRet);
            }
            
            stAns.set_now_hunli(stPlayerBaseInfo._iHunli);
            stAns.set_is_stat_up(bIsStatUp ? 1 : 0);

            if (bIsStatUp)
            {
                MsgSoulInfo* pstMsgSouInfo = stAns.mutable_info();
                pstMsgSouInfo->set_now_skill_id(stPlayerOnlineData._stUserRole.GetMagicSkillID());
                iRet = pstMainCtrl->m_stSoulMgr.GetSoulInfo(stPlayerDetailInfo._stSoulData, *pstMsgSouInfo);

                //新手目标
                pstMainCtrl->m_stNewbieTaskMgr.Trigger(stPlayerDetailEx1Info._stNewbieTaskUserData, uiGID, NEWBIE_TASK_COND_11, 
                                    stPlayerDetailInfo._stSoulData._ucNowStat);
            }

            //重新计算属性, 该函数会自动下发新属性
            pstMainCtrl->m_stNotifyMgr.Notify(stPlayerBaseInfo._uiGID, NOTIFY_ROLE_ATTR);

            //任务触发
            pstMainCtrl->m_stTaskMgr.TriggerDoSomeOpt(stPlayerOnlineData._stUserTask, TASK_OPT_ID_132, 1);

            bNeedSaveData = true;
        }
        break;
    case 3: //换技能
        {
            unsigned int uiSkillID = (unsigned int)stReq.use_skill_id();

            //检查是否可以使用该技能
            if (!pstMainCtrl->m_stSoulMgr.CanUseSkill(stPlayerDetailInfo._stSoulData, stPlayerBaseInfo._ucCareer, uiSkillID))
            {
                return AnsClients(ERROR_SOUL_SKILL_ID);
            }

            //修改当前幻化技能
            iRet = stPlayerOnlineData._stUserRole.ChgMagicSkill(stPlayerBaseInfo, stPlayerDetailInfo, stPlayerOnlineData, uiSkillID);
            if (iRet)
            {
                return AnsClients(iRet);
            }

            pstMainCtrl->m_stNotifyMgr.Notify(uiGID, NOTIFY_ROLE_INFO);

            bNeedSaveData = true;
        }
        break;
    default:
        return AnsClients(RET_SYS_ERROR);
    }

    if (bNeedSaveData)
    {

        CVarObjectKey stKey;
        stKey.m_chDataType = DT_PLAYER_BASE_INFO;
        stKey.m_u64ID = stPlayerBaseInfo._uiGID;
        pstMainCtrl->UpdateData(stKey, stPlayerBaseInfo, VOP_UPDATE);

        stKey.m_chDataType = DT_PLAYER_DETAIL_INFO;
        stKey.m_u64ID = stPlayerDetailInfo._uiGID;
        pstMainCtrl->UpdateData(stKey, stPlayerDetailInfo, VOP_UPDATE);
    }

    return AnsClients(iRet);
}

int CCmdSoul::AnsClients(int iRet)
{
    pstMainCtrl->m_stEncodeBuf.Clear();

    stMsgHead.set_msgret(iRet);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

    if (iRet != RET_OK)
    {
        pstMainCtrl->ReturnMsgHead(stMsgHead, stEnpHead);
        return Done(iRet);
    }

    pstMainCtrl->EncodePBMsg(stMsgHead, pstMainCtrl->m_stEncodeBuf);
    pstMainCtrl->EncodePBMsg(stAns, pstMainCtrl->m_stEncodeBuf);

    if (pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf, true))
    {
        return Done(RET_SYS_ERROR);
    }

    return Done(iRet);
}   
